package com.kuangjia.student_ems.service.impl;

import com.kuangjia.student_ems.dto.UserDTO;
import com.kuangjia.student_ems.dto.request.UserCreateRequest;
import com.kuangjia.student_ems.dto.request.UserUpdateRequest;
import com.kuangjia.student_ems.entity.Department;
import com.kuangjia.student_ems.entity.Position;
import com.kuangjia.student_ems.entity.User;
import com.kuangjia.student_ems.exception.ResourceNotFoundException;
import com.kuangjia.student_ems.repository.DepartmentRepository;
import com.kuangjia.student_ems.repository.PositionRepository;
import com.kuangjia.student_ems.repository.UserRepository;
import com.kuangjia.student_ems.repository.UserMapper;
import com.kuangjia.student_ems.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.beans.factory.annotation.Value;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import java.util.List;
import java.util.stream.Collectors;
import java.util.Map;
import java.util.Set;
import java.time.LocalDate;
import com.kuangjia.student_ems.service.EmailCodeService;

@Service
public class UserServiceImpl implements UserService {
    
    private final UserRepository userRepository;
    private final DepartmentRepository departmentRepository;
    private final PositionRepository positionRepository;
    private final UserMapper userMapper;
    private final BCryptPasswordEncoder passwordEncoder;
    private final EmailCodeService emailCodeService;
    
    @Autowired
    public UserServiceImpl(UserRepository userRepository, 
                          DepartmentRepository departmentRepository,
                          PositionRepository positionRepository,
                          UserMapper userMapper,
                          EmailCodeService emailCodeService) {
        this.userRepository = userRepository;
        this.departmentRepository = departmentRepository;
        this.positionRepository = positionRepository;
        this.userMapper = userMapper;
        this.passwordEncoder = new BCryptPasswordEncoder();
        this.emailCodeService = emailCodeService;
    }
    
    @Override
    @Transactional
    public UserDTO createUser(UserCreateRequest request) {
        if (userRepository.existsByUsername(request.getUsername())) {
            throw new IllegalArgumentException("用户名已存在");
        }
        
        User user = new User();
        user.setUsername(request.getUsername());
        user.setPassword(passwordEncoder.encode(request.getPassword()));
        user.setName(request.getName());
        user.setEmail(request.getEmail());
        user.setPhone(request.getPhone());
        user.setRole(request.getRole());
        
        if (request.getDepartmentId() != null) {
            Department department = departmentRepository.findById(request.getDepartmentId())
                    .orElseThrow(() -> new ResourceNotFoundException("部门", "id", request.getDepartmentId()));
            user.setDepartment(department);
        }
        
        if (request.getPositionId() != null) {
            Position position = positionRepository.findById(request.getPositionId())
                    .orElseThrow(() -> new ResourceNotFoundException("岗位", "id", request.getPositionId()));
            user.setPosition(position);
        }
        
        User savedUser = userRepository.save(user);
        return UserDTO.fromEntity(savedUser);
    }
    
    @Override
    @Transactional
    public UserDTO updateUser(Long userId, UserUpdateRequest request) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("用户", "id", userId));
        
        if (request.getName() != null) {
            user.setName(request.getName());
        }
        
        if (request.getEmail() != null) {
            user.setEmail(request.getEmail());
        }
        
        if (request.getPhone() != null) {
            user.setPhone(request.getPhone());
        }
        
        if (request.getRole() != null) {
            user.setRole(request.getRole());
        }
        
        if (request.getPassword() != null && !request.getPassword().isEmpty()) {
            user.setPassword(passwordEncoder.encode(request.getPassword()));
        }
        
        if (request.getDepartmentId() != null) {
            Department department = departmentRepository.findById(request.getDepartmentId())
                    .orElseThrow(() -> new ResourceNotFoundException("部门", "id", request.getDepartmentId()));
            user.setDepartment(department);
        }
        
        if (request.getPositionId() != null) {
            Position position = positionRepository.findById(request.getPositionId())
                    .orElseThrow(() -> new ResourceNotFoundException("岗位", "id", request.getPositionId()));
            user.setPosition(position);
        }
        
        // 处理员工状态
        if (request.getStatus() != null) {
            user.setStatus(request.getStatus());
            
            // 如果状态改为离职，设置离职日期为当前日期
            if (request.getStatus() == User.EmployeeStatus.LEFT) {
                user.setLeaveDate(LocalDate.now());
            } else if (request.getStatus() == User.EmployeeStatus.ACTIVE) {
                // 如果状态改为在职，清空离职相关信息
                user.setLeaveDate(null);
                user.setLeaveReason(null);
            }
        }
        
        // 处理离职原因
        if (request.getLeaveReason() != null) {
            user.setLeaveReason(request.getLeaveReason());
        }
        
        User updatedUser = userRepository.save(user);
        return UserDTO.fromEntity(updatedUser);
    }
    
    @Override
    @Transactional
    public void deleteUser(Long userId) {
        if (!userRepository.existsById(userId)) {
            throw new ResourceNotFoundException("用户", "id", userId);
        }
        userRepository.deleteById(userId);
    }
    
    @Override
    public UserDTO getUserById(Long userId) {
        User user = userRepository.findByIdWithDepartment(userId)
                .orElseThrow(() -> new ResourceNotFoundException("用户", "id", userId));
        return UserDTO.fromEntity(user);
    }
    
    @Override
    public List<UserDTO> getAllUsers() {
        List<User> users = userRepository.findAll();
        return users.stream()
                .map(UserDTO::fromEntity)
                .collect(Collectors.toList());
    }
    
    @Override
    public List<UserDTO> getUsersByDepartment(Long departmentId) {
        List<User> users = userRepository.findByDepartmentId(departmentId);
        return users.stream()
                .map(UserDTO::fromEntity)
                .collect(Collectors.toList());
    }
    
    @Override
    public List<UserDTO> getUsersByRole(User.UserRole role) {
        List<User> users = userRepository.findByRole(role);
        return users.stream()
                .map(UserDTO::fromEntity)
                .collect(Collectors.toList());
    }
    
    @Override
    public UserDTO getUserByUsername(String username) {
        User user = userRepository.findByUsername(username)
                .orElseThrow(() -> new ResourceNotFoundException("用户", "username", username));
        return UserDTO.fromEntity(user);
    }
    
    @Override
    public boolean existsByUsername(String username) {
        return userRepository.existsByUsername(username);
    }
    
    @Override
    public List<UserDTO> searchUsers(String keyword) {
        if (keyword == null || keyword.trim().isEmpty()) {
            return getAllUsers();
        }
        
        String searchTerm = "%" + keyword.toLowerCase() + "%";
        List<User> users = userRepository.searchUsers(searchTerm);
        return users.stream()
                .map(UserDTO::fromEntity)
                .collect(Collectors.toList());
    }
    
    @Override
    public IPage<UserDTO> getUserPage(Page<User> page, String keyword) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (keyword != null && !keyword.isEmpty()) {
            wrapper.lambda().like(User::getUsername, keyword)
                .or().like(User::getName, keyword)
                .or().like(User::getEmail, keyword)
                .or().like(User::getPhone, keyword)
                .orderByAsc(User::getId);
        } else {
            wrapper.lambda().orderByAsc(User::getId);
        }
        IPage<User> userPage = userMapper.selectPage(page, wrapper);
        // 批量查部门和职位，判空处理
        Set<Long> deptIds = userPage.getRecords().stream()
            .map(User::getDepartmentId)
            .filter(id -> id != null)
            .collect(Collectors.toSet());
        Set<Long> posIds = userPage.getRecords().stream()
            .map(User::getPositionId)
            .filter(id -> id != null)
            .collect(Collectors.toSet());
        System.out.println("[DEBUG] 分页用户的岗位ID集合: " + posIds);
        Map<Long, String> deptMap = deptIds.isEmpty() ? Map.of() : departmentRepository.findAllById(deptIds).stream().collect(Collectors.toMap(d -> d.getId(), d -> d.getName()));
        Map<Long, String> posMap = posIds.isEmpty() ? Map.of() : positionRepository.findAllById(posIds).stream().collect(Collectors.toMap(p -> p.getId(), p -> p.getName()));
        System.out.println("[DEBUG] 岗位ID->名称映射: " + posMap);
        // 转换为DTO并补全名称，所有字段判空
        IPage<UserDTO> dtoPage = userPage.convert(user -> {
            UserDTO dto = new UserDTO();
            dto.setId(user.getId());
            dto.setUsername(user.getUsername());
            dto.setName(user.getName());
            dto.setEmail(user.getEmail());
            dto.setPhone(user.getPhone());
            dto.setRole(user.getRole());
            dto.setStatus(user.getStatus());
            dto.setEntryDate(user.getEntryDate());
            dto.setLeaveDate(user.getLeaveDate());
            dto.setLeaveReason(user.getLeaveReason());
            dto.setCreateTime(user.getCreateTime());
            dto.setUpdateTime(user.getUpdateTime());
            Long deptId = user.getDepartmentId();
            Long posId = user.getPositionId();
            dto.setDepartmentId(deptId);
            dto.setPositionId(posId);
            dto.setDepartmentName(deptId != null ? deptMap.getOrDefault(deptId, "") : "");
            dto.setPositionName(posId != null ? posMap.getOrDefault(posId, "") : "");
            return dto;
        });
        return dtoPage;
    }
    
    @Override
    @Transactional
    public boolean changePassword(Long userId, String oldPassword, String newPassword, String email, String emailCode) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("用户", "id", userId));
        
        // 校验原密码
        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            return false;
        }
        
        // 验证邮箱验证码
        if (!emailCodeService.verifyEmailCode(email, emailCode)) {
            return false;
        }
        
        // 设置新密码
        user.setPassword(passwordEncoder.encode(newPassword));
        userRepository.save(user);
        return true;
    }
} 